using System.Collections.Generic;
using UnityEngine;

public class MapGrid
{
    private Dictionary<Vector2Int, MapVertex> vertexDir = new Dictionary<Vector2Int, MapVertex>();
    private Dictionary<Vector2Int, MapCell> cellDir = new Dictionary<Vector2Int, MapCell>();
    public int MapHeight { get; private set; }
    public int MapWidth { get; private set; }
    public float CellSize { get; private set; }


    public MapGrid(int mapWidth, int mapHeight, float cellSize)
    {
        this.MapWidth = mapWidth;
        this.MapHeight = mapHeight;
        this.CellSize = cellSize;
    }


    public void GenerateMapGrid()
    {
        for (int w = 1; w < MapWidth; w++)
        {
            for (int h = 1; h < MapHeight; h++)
            {
                AddVertex(w, h);
                AddCell(w, h);
            }
        }

        //网格比定点多一行
        for (int w = 1; w <= MapWidth; w++)
        {
            AddCell(w, MapHeight);
        }

        //网格比顶点多一列
        for (int h = 1; h < MapHeight; h++)
        {
            AddCell(MapWidth, h);
        }
    }

    /// <summary>
    /// 通过噪点图计算格子贴图的索引数字
    /// </summary>
    /// <param name="noiseMap"></param>
    /// <param name="limit">不同贴图的分割点</param>
    /// <returns></returns>
    public void CalculateCellTextureIndex(float[,] noiseMap, float limit)
    {
         int xLength = noiseMap.GetLength(0);
         int yLength = noiseMap.GetLength(1);
         for (int i = 1; i < xLength; i++)
         {
             for (int j = 1; j < yLength; j++)
             {
                 var noise = noiseMap[i, j];
                 if (noise > limit)
                 {
                      SetVertexType(new Vector2Int(i, j),MapVertexType.Marsh);
                 }
                 else
                 {
                     SetVertexType(new Vector2Int(i,j),MapVertexType.Forest);
                 }
             }
         }
    }


    /// <summary>
    /// 设置顶点类型，顶点类型决定周围格子的贴图索引
    /// </summary>
    /// <param name="vertexIndex"></param>
    /// <param name="vertexType"></param>
    private void SetVertexType(Vector2Int vertexIndex, MapVertexType vertexType)
    {
        var vertex = GetVertex(vertexIndex);
        if (vertex.VertexType != vertexType)
        {
            vertex.VertexType = vertexType;
            if (vertex.VertexType == MapVertexType.Marsh) //只有在沼泽下才需要计算贴图
            {
                var tmpCell = GetLeftBottomCell(vertexIndex);
                if (tmpCell != null) tmpCell.TextureIndex += 1;
                tmpCell = GetRightBottomCell(vertexIndex);
                if (tmpCell != null) tmpCell.TextureIndex += 2;
                tmpCell = GetLeftTopCell(vertexIndex);
                if (tmpCell != null) tmpCell.TextureIndex += 4;
                tmpCell = GetRightTopCell(vertexIndex);
                if (tmpCell != null) tmpCell.TextureIndex += 8;
            }
        }
    }

    private void SetVertexType(int x, int y, MapVertexType vertexType)
    {
        SetVertexType(new Vector2Int(x, y), vertexType);
    }

    #region Vertex顶点

    public void AddVertex(int w, int h)
    {
        vertexDir.Add(new Vector2Int(w, h), new MapVertex()
        {
            Position = new Vector3(w * CellSize, 0, h * CellSize)
        });
    }


    public MapVertex GetVertex(Vector2Int index)
    {
        vertexDir.TryGetValue(index, out MapVertex vertex);
        return vertex;
    }

    public MapVertex GetVertex(int x, int y)
    {
        return vertexDir[new Vector2Int(x, y)];
    }

    /// <summary>
    /// 从世界坐标获取顶点
    /// </summary>
    /// <param name="worldPosition"></param>
    /// <returns></returns>
    public MapVertex GetVertexByGlobalPosition(Vector3 worldPosition)
    {
        int x = Mathf.Clamp(Mathf.RoundToInt(worldPosition.x / CellSize), 1, MapWidth - 1);
        int z = Mathf.Clamp(Mathf.RoundToInt(worldPosition.z / CellSize), 1, MapHeight - 1);
        return GetVertex(new Vector2Int(x, z));
    }

    #endregion

    #region cell 格子

    public void AddCell(int w, int h)
    {
        float offset = CellSize * 0.5f;
        cellDir.Add(new Vector2Int(w, h), new MapCell()
        {
            Position = new Vector3(w * CellSize - offset, 0, h * CellSize - offset)
        });
    }

    public MapCell GetCell(Vector2Int index)
    {
        cellDir.TryGetValue(index, out MapCell cell);
        return cell;
    }

    public MapCell GetCell(int x, int y)
    {
        return GetCell(new Vector2Int(x, y));
    }

    public MapCell GetLeftBottomCell(Vector2Int index)
    {
        return GetCell(index);
    }

    public MapCell GetRightBottomCell(Vector2Int index)
    {
        return cellDir[new Vector2Int(index.x + 1, index.y)];
    }

    public MapCell GetRightTopCell(Vector2Int index)
    {
        return GetCell(new Vector2Int(index.x + 1, index.y + 1));
    }

    public MapCell GetLeftTopCell(Vector2Int index)
    {
        return GetCell(new Vector2Int(index.x, index.y + 1));
    }

    #endregion
}

public class MapVertex
{
    public Vector3 Position;
    public MapVertexType VertexType;
}

public class MapCell
{
    public Vector3 Position;
    public int TextureIndex { get; set; }
}

public enum MapVertexType
{
    Forest, //森林
    Marsh, //沼泽
}